package com.rkc.service.impl;

import com.alibaba.fastjson.JSON;
import com.rkc.constant.CacheKey;
import com.rkc.enums.BizCodeEnum;
import com.rkc.exception.BizException;
import com.rkc.interceptor.LoginInterceptor;
import com.rkc.model.LoginUser;
import com.rkc.request.CartItemRequest;
import com.rkc.service.CartService;
import com.rkc.service.ProductService;
import com.rkc.vo.CartItemVO;
import com.rkc.vo.CartVO;
import com.rkc.vo.ProductVO;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.BoundHashOperations;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Service;

import java.util.*;
import java.util.function.Function;
import java.util.stream.Collectors;

/**
 * @author `RKC`
 * @date 2021/10/30 15:16
 */
@Service
@Slf4j
public class CartServiceImpl implements CartService {

    @Autowired
    private RedisTemplate<String, Object> redisTemplate;

    @Autowired
    private ProductService productService;

    @Override
    public void addToCart(CartItemRequest cartItemRequest) {
        long productId = cartItemRequest.getProductId();
        int buyNum = cartItemRequest.getBuyNum();
        String cartKey = getCartKey();
        BoundHashOperations<String, Object, Object> cartHash = redisTemplate.boundHashOps(cartKey);
        Object cacheObj = cartHash.get(productId);
        String cacheCartItemString = "";
        if (cacheObj != null) {
            cacheCartItemString = (String) cacheObj;
        }
        if (StringUtils.isBlank(cacheCartItemString)) {
            //不存在则新建商品
            CartItemVO cartItemVO = new CartItemVO();
            ProductVO productVO = productService.detailById(productId);
            if (productVO == null) {
                throw new BizException(BizCodeEnum.CART_FAIL);
            }
            cartItemVO.setAmount(productVO.getAmount());
            cartItemVO.setBuyNum(buyNum);
            cartItemVO.setProductId(productId);
            cartItemVO.setProductImg(productVO.getCoverImg());
            cartItemVO.setProductTitle(productVO.getTitle());
            cartHash.put(productId, JSON.toJSONString(cartItemVO));
        } else {
            //添加数量
            CartItemVO cartItemVO = JSON.parseObject(cacheCartItemString, CartItemVO.class);
            cartItemVO.setBuyNum(cartItemVO.getBuyNum() + buyNum);
            cartHash.put(productId, JSON.toJSONString(cartItemVO));
        }
    }

    /**
     * 清空购物车
     */
    @Override
    public void clear() {
        redisTemplate.delete(getCartKey());
    }

    @Override
    public CartVO findMyCart() {
        //获取全部购物项
        List<CartItemVO> cartItemVOList = buildCartItem(false);
        CartVO cartVO = new CartVO();
        cartVO.setCartItems(cartItemVOList);
        return cartVO;
    }

    /**
     * 删除购物项
     * @param productId
     */
    @Override
    public void deleteItem(long productId) {
        BoundHashOperations<String, Object, Object> cartHash = redisTemplate.boundHashOps(getCartKey());
        cartHash.delete(productId);
    }

    /**
     * 修改购物项数量
     * @param cartItemRequest
     */
    @Override
    public void updateItemCount(CartItemRequest cartItemRequest) {
        BoundHashOperations<String, Object, Object> cartHash = redisTemplate.boundHashOps(getCartKey());
        Object obj = cartHash.get(cartItemRequest.getProductId());
        if (obj == null) {
            throw new BizException(BizCodeEnum.CART_FAIL);
        }
        CartItemVO cartItemVO = JSON.parseObject((String) obj, CartItemVO.class);
        cartItemVO.setBuyNum(cartItemRequest.getBuyNum());
        cartHash.put(cartItemRequest.getProductId(), JSON.toJSONString(cartItemVO));
    }

    /**
     * 确认购物车商品信息
     * @param productIdSet
     * @return
     */
    @Override
    public List<CartItemVO> confirmOrderCartItem(Set<Long> productIdSet) {
        //获取全部购物车的购物项，且标注最新价格
        List<CartItemVO> cartItemVOList = buildCartItem(true);
        //用productIdSet对购物车的商品进行过滤
        return cartItemVOList.stream().filter(obj -> productIdSet.contains(obj.getProductId())).collect(Collectors.toList());
    }

    /**
     * 获取最新的购物项
     * @param latestPrice 是否获取最新价格
     * @return
     */
    private List<CartItemVO> buildCartItem(boolean latestPrice) {
        BoundHashOperations<String, Object, Object> cartHash = redisTemplate.boundHashOps(getCartKey());
        List<Object> itemList = cartHash.values();
        List<CartItemVO> cartItemVOList = new ArrayList<>(itemList.size());
        List<Long> productIdList = new ArrayList<>(itemList.size());
        for (Object item : itemList) {
            CartItemVO cartItemVO = JSON.parseObject((String) item, CartItemVO.class);
            cartItemVOList.add(cartItemVO);
            productIdList.add(cartItemVO.getProductId());
        }
        //查询最新的价格
        if (latestPrice) {
            setProductLatestPrice(cartItemVOList, productIdList);
        }
        return cartItemVOList;
    }

    /**
     * 设置商品最新价格
     * @param cartItemVOList
     * @param productIdList
     */
    private void setProductLatestPrice(List<CartItemVO> cartItemVOList, List<Long> productIdList) {
        List<ProductVO> productVOList = productService.findProductsByIdBatch(productIdList);
        //流根据id进行分组转化为map
        Map<Long, ProductVO> idToProduct = productVOList.stream().collect(Collectors.toMap(ProductVO::getId, Function.identity()));
        cartItemVOList.forEach(item -> {
            ProductVO productVO = idToProduct.get(item.getProductId());
            item.setProductTitle(productVO.getTitle());
            item.setProductImg(productVO.getCoverImg());
            item.setAmount(productVO.getAmount());
        });
    }

    private String getCartKey() {
        LoginUser loginUser = LoginInterceptor.THREAD_LOCAL.get();
        return String.format(CacheKey.CART_KEY, loginUser.getId());
    }
}
